package wiiusej.apptest;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


import sun.font.CreatedFontTracker;
import wiiusej.*;
import wiiusej.apptest.activityTasks.ComClient;
import wiiusej.apptest.activityTasks.EnergyTransmisionTask;
import wiiusej.apptest.activityTasks.Spell;
import wiiusej.apptest.activityTasks.SpellGameTask;
import wiiusej.connection.ConnectionManager;

import wiiusej.wiiusejevents.GenericEvent;
import wiiusej.wiiusejevents.utils.WiimoteListener;
import wiiusej.wiiusejevents.wiiuseapievents.WiiUseApiEvent;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.spi.RootLogger;

public class WiimoteMain extends Thread{

	
	private static BlockingQueue<Spell> eneergyToComClient = new LinkedBlockingDeque<Spell>();
	
	private static final int NTHREADS = 200;
	
	private static final ExecutorService exec = 
		Executors.newFixedThreadPool(NTHREADS);
	
	private static HashMap<Integer, Wiimote> wiimotes;
	
	//Logger	
	private static Logger fileLogger;
	
	static private BlockingQueue<HashMap<Integer, BlockingQueue<GenericEvent>>> connectionToAPI;
	static private BlockingQueue<WiiUseApiEvent> apiToConnection;
	static private BlockingQueue<WiiUseApiEvent> postmanToNetListener;
	
	//Components
	static private WiiUseApiManager controller;
	static private ConnectionManager connectionManager;
	static private MessageDeliver messageDeliver;	
	
	private static String[] inputParameters; 
	private static Integer[] simParameters; 
	
	private static int runMode; //normal or network
	private static int simulationLength; //packets per simulation
	private static int timeout; //milliseconds
	
	
	private final static int NORMAL = 0; 
	private final static int NET = 1;
	
	
	public static void main(String[] args) {

		//Log configuration
		PropertyConfigurator.configure("log4j.properties");
		fileLogger = Logger.getLogger("main");
		
		//we got the input parameters
		inputParameters = args;		
			
	}		
		
	private static boolean getInputParameters(String[] args) {
		
		runMode = Integer.parseInt(args[0]);
		fileLogger.info("RunMode: " + runMode + "  ArgumentEntered: " + args[0]);
		
		if(runMode == NET){			
			
			if(args[1] == null || Integer.parseInt(args[1]) < 1 
					|| args[2] == null || Integer.parseInt(args[2]) < 1){
				
				//the simulation cannot continue	
				fileLogger.error("NO VALID INPUT PARAMETERS");
				return false;			
			}		
		}
		
		return true;
		
		
	}

	private static void selectMode() {

		//COM queues
		initQueues();
		
		//Init the architecture
		if(runMode == NET){
			initComponents(false);			
		}else{			
			initComponents(true);	
		}
		
	}

	public void run(){
		
		boolean run; 
		run = getInputParameters(inputParameters);	
		
		if(run){		
			//decide in which mode should the main build the architecture
			selectMode();
			
			
			switch(runMode){
			
			case 0:
				fileLogger.info("Normal MODE");
				
				while(true){
					
				}				
				
			case 1: 
				fileLogger.info("Simulation MODE");
				
				
				
				
				break;
				
			
			}
			
				
		}else{
			//something went wrong
			fileLogger.error("FINISHING THE APP!!");
		}
		
		
	}
	
	
	
	protected static void initQueues(){		
		//COM queue from Connection Manager to WiiuseApiListener
		connectionToAPI = 
			new LinkedBlockingQueue<HashMap<Integer, BlockingQueue<GenericEvent>>>();		
		//COM queue from WiiuseApiListener to ConnectionManager - Inform about Disconnection Events
		apiToConnection = new LinkedBlockingDeque<WiiUseApiEvent>();
		
		postmanToNetListener = new LinkedBlockingDeque<WiiUseApiEvent>();
	}
	
	protected static void initComponents(boolean mode){
		
		//API listener
		controller = new WiiUseApiManager();
		
		//Connection controller
		Runnable connection = 
			new ConnectionManager(exec, controller, connectionToAPI, eneergyToComClient, apiToConnection, 
					postmanToNetListener, inputParameters);
		exec.execute(connection);
		
		//Message delivery system
		Runnable postman = 
			new MessageDeliver(connectionToAPI, apiToConnection, controller, postmanToNetListener);		
		exec.execute(postman);
		
		
		
		//Runnable gameController = 
			//new SpellGameTask(realTimeToGameController, gameToEnergy, toRumbleQ, fromEnergyToGameQ, wiimote);
		
	}
	
	protected boolean shutdownApp(){
		
		return false;
	}
	
	
	protected static void initComClient(){
		
		Runnable clientServer = 
			new ComClient(eneergyToComClient, wiimotes);
		
		exec.execute(clientServer);
		
	}
	
	
}

	
